/*----------------------------------------------------------------------------*\
|
|						Public Interface to Muse Technology
|
|							     www.Muse.com
| Author : SunJun 
| Email : sundoom@msn.com
\*----------------------------------------------------------------------------*/

//////////////////////////////////////////////////////////////////////////
// $Id: MPtr.h,v 1.1 2009/04/03 12:46:09 sunjun Exp $
//////////////////////////////////////////////////////////////////////////

#ifndef __MPtr__
#define __MPtr__

//////////////////////////////////////////////////////////////////////////

#if defined __cplusplus

//////////////////////////////////////////////////////////////////////////

#include <Muse.h>

//////////////////////////////////////////////////////////////////////////

NAMESPACE_BEGIN

//////////////////////////////////////////////////////////////////////////	

	// smart pointer for handling referenced counted objects.
	template<class T>
	class MPtr
	{
	private: 
		typedef T* MPtr::*bool_type;
		T* mPtr;

	public: 
		typedef T element_type;
		
		INLINE MPtr() : mPtr(0)
		{
			GUARD(MPtr());

			UNGUARD;
		}

		INLINE MPtr( T* ptr ) : mPtr(ptr) 
		{
			GUARD(MPtr( T* ptr ));

			if( mPtr ) mPtr->ref(); 

			UNGUARD;
		}

		INLINE MPtr( const MPtr& rp ) : mPtr( rp.mPtr ) 
		{
			GUARD(MPtr( const MPtr& rp ));

			if( mPtr ) mPtr->ref(); 

			UNGUARD;
		}
		
		INLINE ~MPtr() 
		{
			GUARD(~MPtr);

			if( mPtr ) mPtr->unref();  
			mPtr = 0; 

			UNGUARD;
		}
		
		INLINE MPtr& operator = ( const MPtr& rp )
		{
			GUARD(operator = ( const MPtr& rp ));

			if( mPtr == rp.mPtr ) return *this;
			T* tmp_ptr = mPtr;
			mPtr = rp.mPtr;
			if( mPtr ) mPtr->ref();
			if( tmp_ptr ) tmp_ptr->unref();
			return *this;

			UNGUARD;
		}
		
		INLINE MPtr& operator = ( T* ptr )
		{
			GUARD(operator = ( T* ptr ));

			if( mPtr == ptr ) return *this;
			T* tmp_ptr = mPtr;
			mPtr = ptr;
			if( mPtr ) mPtr->ref();
			if( tmp_ptr ) tmp_ptr->unref();
			return *this;

			UNGUARD;
		}
		
		INLINE BOOL operator == ( const MPtr& rp ) const 
		{
			GUARD(operator == ( const MPtr& rp ));

			return ( mPtr == rp.mPtr ) ? TRUE : FALSE;

			UNGUARD;
		}
		
		INLINE BOOL operator == ( const T* ptr ) const 
		{
			GUARD(operator == ( const T* ptr ));

			return ( mPtr == ptr ) ? TRUE : FALSE;

			UNGUARD;
		}

		INLINE friend BOOL operator == ( const T* ptr, const MPtr& rp ) 
		{
			GUARD(operator == ( const T* ptr, const MPtr& rp ));

			return ( ptr == rp.mPtr ) ? TRUE : FALSE; 

			UNGUARD;
		}
		
		INLINE BOOL operator != ( const MPtr& rp ) const 
		{
			GUARD(operator != ( const MPtr& rp ));

			return ( mPtr != rp.mPtr ) ? TRUE : FALSE; 

			UNGUARD;
		}

		INLINE BOOL operator != ( const T* ptr ) const 
		{
			GUARD(operator != ( const T* ptr ));

			return ( mPtr != ptr ) ? TRUE : FALSE; 

			UNGUARD;
		}

		INLINE friend BOOL operator != ( const T* ptr, const MPtr& rp ) 
		{
			GUARD(operator != ( const T* ptr, const MPtr& rp ));

			return ( ptr != rp.mPtr ) ? TRUE : FALSE; 

			UNGUARD;
		}
		
		INLINE T& operator*() const 
		{
			GUARD(operator*());

			return *mPtr; 

			UNGUARD;
		}

		INLINE T* operator->() const 
		{
			GUARD(operator->());

			return mPtr; 

			UNGUARD;
		}

		INLINE T* ptr() const 
		{
			GUARD(ptr());

			return mPtr; 

			UNGUARD;
		}
		
		INLINE BOOL operator!() const
		{
			GUARD(operator!());

			return mPtr == 0 ? TRUE : FALSE;

			UNGUARD;
		} 

		INLINE BOOL valid() const       
		{
			GUARD(valid());

			return mPtr != 0 ? TRUE : FALSE;

			UNGUARD;
		}
		
		INLINE VOID release() 
		{
			GUARD(release());

			if(mPtr) mPtr->unref(); 
			mPtr = 0;

			UNGUARD;
		}

		INLINE operator bool_type() const 
		{ 
			GUARD(operator bool_type());

			return mPtr != 0 ? &MPtr::mPtr : 0; 

			UNGUARD;
		}
	};

	//////////////////////////////////////////////////////////////////////////

	template<class T, class Y> INLINE MPtr<T> static_ptr_cast( const MPtr<Y>& rp ) 
	{ 
		GUARD(static_ptr_cast);

		return static_cast<T*>(rp.ptr()); 

		UNGUARD;
	}

	template<class T, class Y> INLINE MPtr<T> dynamic_ptr_cast( const MPtr<Y>& rp ) 
	{ 
		GUARD(dynamic_ptr_cast);

		return dynamic_cast<T*>(rp.ptr()); 

		UNGUARD;
	}

	template<class T, class Y> INLINE MPtr<T> const_ptr_cast( const MPtr<Y>& rp ) 
	{ 
		GUARD(const_ptr_cast);

		return const_cast<T*>(rp.ptr()); 

		UNGUARD;
	}

//////////////////////////////////////////////////////////////////////////

NAMESPACE_END

//////////////////////////////////////////////////////////////////////////

#endif // __cplusplus

//////////////////////////////////////////////////////////////////////////

#endif // __MPtr__

//////////////////////////////////////////////////////////////////////////